#include <assert.h>
#include <ctype.h>
#include <locale.h>
#include <errno.h>
#include <float.h>
#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <pthread.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdnoreturn.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include<windows.h>

/*
The volatile keyword tells the compiler that the value of the variable may change at any time as a result of
external conditions, not only as a result of program control flow.
The compiler will not optimize anything that has to do with the volatile variable.

There are two main reasons to uses volatile variables:
    1. To interface with hardware that has memory-mapped I/O registers.
    2. When using variables that are modified outside the program control flow (e.g., in an interrupt service routine)
*/

int quit = false;

void interrupt_handler(void)
{
quit = true;
}

void volatile_variables(void)
{
    printf("***** volatile_variables *****\n");
    // volatile int foo; /* Different ways to declare a volatile variable */
    // int volatile foo;
    // volatile uint8_t * pReg; /* Pointers to volatile variable */
    // uint8_t volatile * pReg;

    while(!quit)
    {
        /*
        Do something that does not modify the quit variable
        
        The compiler is allowed to notice the while loop does not modify the quit variable and convert the loop to a
        endless while (true) loop. Even if the quit variable is set on the signal handler for SIGINT and SIGTERM, the
        compiler does not know that.
        
        Declaring quit as volatile will tell the compiler to not optimize the loop and the problem will be solved.
        */
       printf("while(true)\n");
    }
    
}

void unmodifiable_const_variables(void)
{
    printf("***** unmodifiable_const_variables *****\n");
    // The const qualification only means that we don't have the right to change the data. 
    // It doesn't mean that the value cannot change behind our back.
    const int a = 0; /* This variable is "unmodifiable", the compiler
    should throw an error when this variable is changed */

    int b = 0; /* This variable is modifiable */

    // Variables with const qualification could still be changed using pointers:
    const int const_a = 0;
    int *a_ptr = (int*)&const_a; /* This conversion must be explicitly done with a cast */
    *a_ptr += 10; /* This has undefined behavior */
    printf("a = %d\n", const_a); /* May print: "a = 10" */
}




void main(void)
{
    // volatile_variables();
    unmodifiable_const_variables();
    system("pause");
}